//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "ddk.h"
#include "elapi.h"
#include "stub.h"
#include "eltypes.h"
#include "Jffs2FileSystem.h"
#include "FileSystemControl.h"

class Jffs2Dev : public CDeviceDriver
{
public:
    CARAPI Read(
                    /* [in] */ Int64 u64Offset,
                    /* [in] */ Int32 uNumberOfBytesToRead,
                    /* [out] */ MemoryBuf * pData,
                    /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
                    /* [in] */ Int64 u64Offset,
                    /* [in] */ const MemoryBuf & ebbData,
                    /* [out] */ Int32 * puNumberOfBytesWritten,
                    /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
                    /* [in] */ Handle32 nControlCode,
                    /* [in] */ const MemoryBuf & ebbInData,
                    /* [out] */ MemoryBuf * pOutData,
                    /* [out] */ IEvent * * ppCompletionEvent);
    virtual ~Jffs2Dev();
    virtual void Dispose();
};

CARAPI Jffs2Dev::Read(
                /* [in] */ Int64 u64Offset,
                /* [in] */ Int32 uNumberOfBytesToRead,
                /* [out] */ MemoryBuf * pData,
                /* [out] */ IEvent * * ppCompletionEvent)
{
    return NOERROR;
}

CARAPI Jffs2Dev::Write(
                /* [in] */ Int64 u64Offset,
                /* [in] */ const MemoryBuf & ebbData,
                /* [out] */ Int32 * puNumberOfBytesWritten,
                /* [out] */ IEvent * * ppCompletionEvent)
{
    return NOERROR;
}

CARAPI Jffs2Dev::Control(
                /* [in] */ Int32 nControlCode,
                /* [in] */ const MemoryBuf & ebbInData,
                /* [out] */ MemoryBuf * pOutData,
                /* [out] */ IEvent * * ppCompletionEvent)
{
    wchar_t *serviceName = NULL;
    IBasicFileSystem *pIBFS = NULL;
    ECode ec;
    IStub *pStub = NULL;

    if (ebbInData.IsNullOrEmpty()) {
        return E_INVALID_ARGUMENT;
    }
    serviceName = (wchar_t *)ebbInData.GetPayload();
    assert(wcslen(serviceName) > 0);

    switch (nControlCode) {
        case FILESYSTEM_CONTROL_CREATE:
            pIBFS = new CJffs2FileSystem();
            if (NULL == pIBFS) {
                kprintf("Create File System failed\n");
                return E_OUT_OF_MEMORY;
            }
            pIBFS->AddRef();

            ec = DzRegisterService(serviceName, pIBFS, &pStub);
            if (ec != NOERROR) {
                kprintf("Register service failed\n");
                delete pIBFS;
                return ec;
            }
            assert(pStub != NULL);
            ((CJffs2FileSystem*)pIBFS)->SetStub(pStub);
            pIBFS->Release();

            kprintf("OK.\n");
            break;

        case FILESYSTEM_CONTROL_DELETE:
            ec = DzFindService(serviceName, (PInterface *)&pIBFS);
            if (ec != NOERROR) {
                kprintf("Find service failed.\n");
                return ec;
            }

            pStub = ((CJffs2FileSystem*)pIBFS)->GetStub();
            assert(pStub != NULL);

            ec = DzUnregisterService(serviceName, pStub);
            if (ec != NOERROR) {
                kprintf("Unregisterservice failed.\n");
                return ec;
            }

            pIBFS->Release();
            break;

        default:
            break;
    }
    return NOERROR;
}

Jffs2Dev::~Jffs2Dev()
{
    this->Release();
}

void Jffs2Dev::Dispose()
{
    delete this;
}

EXTERN IDeviceDriver * CDECL CreateJffs2(uint_t uDeviceNo, void *pvParameter)
{
    Jffs2Dev *pJffs2Driver = new Jffs2Dev();
    if (NULL == pJffs2Driver) {
        return NULL;
    }
    pJffs2Driver->AddRef();
    kprintf("create Jffs2Driver success.\n");
    return pJffs2Driver;
}
